<?php

Raise::load('core.RaiseObject');
Raise::load('core.RaiseRegexMatch');
Raise::load('core.RaiseRegexMatchCollection');
Raise::load('core.RaiseVariable');
Raise::load('core.RaiseCollection');

/**
 * RaiseRegex class
 * provides functionality to regular expression matching and replacement
 *
 * @author Sam-Mauris Yong <hellclanner at live dot com>
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package Raise.Core.Text.Regex
 * @since 1.2
 */
class RaiseRegex extends RaiseObject {

    /**
     * The regular expression that is used in this RaiseRegex
     * @var string
     */
    private $regex;

    /**
     * Create a new RaiseRegex
     * @param string $regex The pattern that this RaiseRegex will use
     */
    public function __construct($regex){
        $this->regex($regex);
    }

    /**
     * Get or set the regular expression that is used in this RaiseRegex
     * @param string $r (optional) If present, the old value will be overriden by this value.
     * @return string
     */
    public function regex($r = null){
        if(func_num_args() == 1){
            $this->regex = $r;
        }
        return $this->regex;
    }

    /**
     * Perform a perl-compatible regular expression (PCRE) match to match within the subject
     * @param string $subject The input string
     * @return RaiseRegexMatchCollection A RaiseRegexMatchCollection that contains all the RaiseRegexMatch found in the subject
     * @link http://php.net/manual/en/function.preg-match.php
     */
    public function match($subject){
        preg_match($this->regex(), $subject, $m);
        $result = new RaiseRegexMatchCollection();
        foreach($m as $a){
            $result->add(new RaiseRegexMatch($this, $a));
        }
        return $result;
    }

    /**
     * Perform a perl-compatible regular expression (PCRE) match to match all matches within the subject
     * @param string $subject The input string
     * @return RaiseCollection The collection of RaiseRegexMatchCollection
     * @link http://www.php.net/manual/en/function.preg-match-all.php
     */
    public function matchAll($subject){
        preg_match_all($this->regex(), $subject, $m, PREG_SET_ORDER);
        $finalResult = new RaiseCollection();
        foreach($m as $a){
            $result = new RaiseRegexMatchCollection();
            foreach($a as $c){
                $result->add(new RaiseRegexMatch($this, $a));
            }
            $finalResult[] = $result;
        }
        return $finalResult;
    }

    /**
     * Perform a perl-compatible regular expression search and replace
     * @param string $subject The input string
     * @param string|array|RaiseCollection $replacement The string or collection of replacements
     * @param integer $limit (Optional) If set, the number of search and replace operations will be limited by this limit.
     * @return string|RaiseCollection
     * @link http://www.php.net/manual/en/function.preg-replace.php
     */
    public function replace($subject, $replacement, $limit = -1){
        $r = preg_replace($this->regex, $replacement, $subject, $limit);
        if(RaiseVariable::isType($r, 'array')){
            $r = new RaiseCollection($r);
        }
        return $r;
    }

    /**
     * Perform a perl-compatible regular expression search and replaceusing a callback
     * @param string $subject The input string
     * @param callback $callback A callback that will be called and passed an array of matched elements in the subject string. The callback should return the replacement string.
     * @param integer $limit (Optional) If set, the number of search and replace operations will be limited by this limit.
     * @return string|RaiseCollection
     * @link http://www.php.net/manual/en/function.preg-replace-callback.php
     */
    public function replaceCallback($subject, $callback, $limit = -1){
        $r = preg_replace_callback($this->regex, $callback, $subject, $limit);
        if(RaiseVariable::isType($r, 'array')){
            $r = new RaiseCollection($r);
        }
        return $r;
    }

}
